﻿using System;
using System.Collections.Generic;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using LEDControllerTools.Controller;
using PIC.Communication;

namespace LEDControllerTools.Commands
{

    [Serializable]
    public class Rs232CommandFactory : ICommandFactory
    {


        private SerialPort SerialPort { get; set; }


        public string PortName
        {
            get { return SerialPort.PortName; }
            set { SerialPort.PortName = value; }
        }

        public int BaudRate
        {
            get { return SerialPort.BaudRate; }
            set { SerialPort.BaudRate = value; }
        }
        
        public Parity Parity
        {
            get { return SerialPort.Parity; }
            set { SerialPort.Parity = value; }
        }

        public int DataBits
        {
            get { return SerialPort.DataBits; }
            set { SerialPort.DataBits = value; }
        }

        public StopBits StopBits
        {
            get { return SerialPort.StopBits; }
            set { SerialPort.StopBits = value; }
        }


        public Rs232CommandFactory()
        {
            SerialPort = new SerialPort();
        }


        public IExecutable GetBatteryCommand()
        {
            var command = new Rs232Command(SerialPort, ControllerDefinition.GetDefinition().BatteryCommand);
            return command;
        }


        public IDictionary<string, IToggleable> GetDigitalOutputCommands()
        {
            var digitalOutputs = new Dictionary<string, IToggleable>();
            var definition = ControllerDefinition.GetDefinition();

            foreach (var command in definition.DigitalCommands)
            {
                var channel = BuildDigitalOutput(command.Key, command.Value.On, command.Value.Off);
                digitalOutputs.Add(command.Key, channel);
            }
                
            return digitalOutputs;
        }

        public IBatteryVoltageResponder GetBatteryVoltageResponse()
        {
            return new Rs232BatteryVoltageResponder(SerialPort);
        }

        private DigitalOutCommand BuildDigitalOutput(string id, string onCommand, string offCommand)
        {
            return new DigitalOutCommand(id, BuildCommand(onCommand), BuildCommand(offCommand));
        }


        private Rs232Command BuildCommand(string command)
        {
            return new Rs232Command(SerialPort, command);
        }




        class Rs232BatteryVoltageResponder : IBatteryVoltageResponder
        {

            public event BatteryVoltageEventHandler BatteryUpdate;

            private SerialPort SerialPort { get; set; }


            public Rs232BatteryVoltageResponder(SerialPort serialPort)
            {
                SerialPort = serialPort;
                serialPort.DataReceived += serialPort_DataReceived;
            }

            void serialPort_DataReceived(object sender, SerialDataReceivedEventArgs e)
            {
                var data = SerialPort.ReadLine();
                var battery = Convert.ToSingle(data);
                OnBatteryUpdate(sender, new BatteryVoltageEventArgs(battery, DateTime.Now));
            }


            protected virtual void OnBatteryUpdate(object sender, BatteryVoltageEventArgs e)
            {
                if (BatteryUpdate != null)
                    BatteryUpdate(sender, e);
            }

        }


    }


}
